package de.rs.espresso.interfaces;

import de.rs.espresso.algorithms.model.FreeSet;

public interface ICube extends Cloneable {
	
	// equals 0b111111 .... 1111;
	static final long DONT_CARE_LONG = -1;
	
	static final long MASK_NEG_6_BIT = DONT_CARE_LONG << 6;
	static final long MASK_6_BIT = 127;
	static final long MASK_5_BIT = 63;
	
	static final long MASK_1_BIT = 1;
	static final long MASK_2_BIT = 3;
	static final long MASK_2_BIT_NEGATED = ~MASK_2_BIT;
	
	static final long VARIABLE_NEGATED = 2;
	static final long VARIABLE_DIRECT = 1;
	
	
	static final byte VOID = 0;
	static final byte NEGATED = 2;
	static final byte DIRECT = 1;
	static final byte DONT_CARE = 3;
	static final byte OUTPUT_PRESENT = 1;
	static final byte OUTPUT_NOT_PRESENT = 0;	
	
	/**
	 * Adds the cube to the given columnCount of a ICover.
	 * 
	 * @param columnCount
	 * @return
	 */
	public int[] addToColumnCount(int[] columnCount);
	
	/**
	 * Adds the cube to the given directNegatedCount of a ICover. 
	 */
	public int[][] addToDirectNegatedCount(int[][] directNegatedCount);

	/**
	 * Returns the Bitwise and-junction of the given and this <code>ICube</code>. 
	 * @param cube
	 * @return
	 */
	public ICube and(ICube cube);
	
	public ICube clone();
	
	/**
	 * Counts the Literals wich are set to Don't Care in this ICube
	 * @return number of literals
	 */
	public int countDontCares();
	
	public boolean covers(ICube otherCube);
	
	public String getBlifString();
	
	/**
	 * Returns the Cofactor of this <code>ICube</code> in respect to the given <code>ICube</code>.
	 * @param cube
	 * @return
	 */
	public ICube getCofactor(ICube cube);
	
	/**
	 * Returns the Complement of this ICube.
	 * @return
	 */
	public ICover getComplement();

	/**
	 * Returns the weight of the cube in the set with the given columnCount.
	 * @param columnCount
	 * @return
	 */
	public int getCubeWeight(int[] columnCount);
	
	public int getDistance(ICube otherCube);
	
	public FreeSet getFreeSet();

	/**
	 * Returns the value of the literal at the given <code>position</code>.
	 * 
	 * @param position
	 * @return value of the literal
	 */
	public byte getLiteral(int position);

	/**
	 * Returns the number of literals stored in this cube.
	 * @return
	 */
	public int getNumberOfLiterals();

	/**
	 * Returns the number of outputs stored in this cube.
	 * @return
	 */
	public int getNumberOfOutputs();

	
	/**
	 * Returns the output at the given <code>position</code>.
	 * @return
	 */
	public byte getOutput(int position);
	
	public ICube getOverexpandedCube(FreeSet fSet);
	
	/**
	 * Returns the supercube of this cube an the given other <code>ICube</code>
	 * 
	 * @param otherCube
	 * @return the supercube of two cubes
	 */
	public ICube getSupercube(ICube otherCube);

	
	/**
	 * Returns <code>true</code>, if there is an intersection between this cube and the given other cube at <code>position</code>
	 * @param otherCube
	 * @param position
	 * @return
	 */
	public boolean intersectAt(ICube otherCube, int position);

	public boolean isAlreadyExpanded();
	
	
	/**
	 * Returns <code>true</code>, if the Bit on <code>position</code> is 1, otherwise <code>false</code>.
	 * 
	 * @param position
	 * @return
	 */
	public boolean isPartSet(int position);

	/**
	 * Checks, whether the cube is completely filled with don't cares.
	 * The result is <code>true</code>, if there are only don't cares in this cube, <code>false</code>, if not.
	 * @return boolean
	 */
	public boolean isTautology();

	
	/**
	 * Checks, whether there are any void literals in this cube.
	 * The result is <code>true</code>, if there are void literals and <code>false</code>, if not.
	 * 
	 * @return boolean
	 */
	public boolean isVoid();
	
	/**
	 * Returns <code>true</code>, if the cube contains a void literal at the given <code>position</code>.
	 * @param position
	 * @return
	 */
	public boolean isVoidAt(int position);
	
	/**
	 * Lowers the 1 at the given <code>position</code> to a 0
	 * @param position
	 */
	public void lowerPart(int position);

	/**
	 * Returns the Bitwise or-junction of the given and this <code>ICube</code>. 
	 * @param cube
	 * @return
	 */
	public ICube or(ICube cube);

	/**
	 * Raises the 0 at the given <code>position</code> to a 1
	 * @param position
	 */
	public void raisePart(int position);
	
	public void setAlreadyExpanded(boolean isAlreadyExpanded);
	
	/**
	 * Sets the value of the literal at the given <code>position</code> to the given <code>value</code>.
	 * 
	 * @param position
	 * @param value
	 */
	public void setLiteral(int position, byte value);

	/**
	 * Sets the cubes ouput on position <code> position </code> according to <code> value </code>. 
	 */
	public void setOutput(int position, byte value);

	
	
	

}
